// 为保持和vue2版本中使用bus一致，emit,on,off,once前面都加了$

class Bus {
  private list: { [key: string]: Function[] };
  constructor() {
    // 收集订阅信息,调度中心
    this.list = {};
  }

  /**
   * @description:订阅
   * @author: zhc
   * @param {string} name 事件名称
   * @param {Function} fn 事件触发时的回调函数
   * @return {Function} 返回传入的事件  可用于取消订阅
   */
  $on(name: string, func: Function): Function {
    this.list[name] = this.list[name] || [];
    this.list[name].push(func);
    return func;
  }
  /**
   * @description:只监听一次 监听完自动销毁
   * @author: zhc
   * @param {string} name 监听的事件名称
   * @return {Function} func 事件触发的回调函数
   */
  $once(name: string, func: Function): Function {
    this.list[name] = this.list[name] || [];
    //挂载函数原型做标识
    func.prototype.once = true;
    this.list[name].push(func);
    return func;
  }

  /**
   * @description:发布事件
   * @author: zhc
   * @param {name} 事件名称
   * @param {data} 函数触发时携带的参数
   */
  $emit(name: string, data?: any): void {
    if (this.list[name]) {
      this.list[name] = this.list[name].filter((fn: any) => {
        fn(data);
        return !Object.prototype.hasOwnProperty.call(fn.prototype, "once");
      });
    }
  }

  /**
   * @description: 取消订阅 事件销毁时 可销毁指定订阅函数 不影响同事件下的其他订阅
   * @author: zhc
   * @param {string} name 事件名称
   * @param {Function} func 订阅时传入的回调函数 不传入则删除全部事件监听
   */
  $off(name: string, func?: Function): void {
    if (func) {
      this.list[name] = this.list[name].filter((item: Function) => {
        return item !== func;
      });
    } else {
      if (this.list[name]) {
        delete this.list[name];
      }
    }
  }
}
export default new Bus();
